/*!
 * \file WtEngine.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief WonderTrader交易引擎基类定义
 * 
 * \details 该文件定义了WonderTrader的核心交易引擎基类WtEngine，提供：
 *          - 统一的交易引擎接口和基础功能
 *          - 行情数据处理和订阅管理
 *          - 风险监控和资金管理
 *          - 信号过滤和执行管理
 *          - 持仓管理和盈亏计算
 *          - 事件通知和任务调度
 */
#pragma once
#include <queue>
#include <functional>
#include <stdint.h>

#include "ParserAdapter.h"
#include "WtFilterMgr.h"


#include "../Includes/FasterDefs.h"
#include "../Includes/RiskMonDefs.h"

#include "../Share/StdUtils.hpp"
#include "../Share/DLLHelper.hpp"

#include "../Share/BoostFile.hpp"


NS_WTP_BEGIN
class WTSSessionInfo;
class WTSCommodityInfo;
class WTSContractInfo;

class IBaseDataMgr;
class IHotMgr;

class WTSVariant;

class WTSTickData;
struct WTSBarStruct;
class WTSTickSlice;
class WTSKlineSlice;
class WTSPortFundInfo;

class WtDtMgr;
class TraderAdapterMgr;

class EventNotifier;

/*!
 * \brief 任务项类型定义
 * \details 用于后台任务队列的函数对象类型
 */
typedef std::function<void()>	TaskItem;

/*!
 * \class WtRiskMonWrapper
 * \brief 风险监控器包装类
 * 
 * \details 提供风险监控器的RAII管理，确保风险监控器的正确创建和销毁
 */
class WtRiskMonWrapper
{
public:
	/*!
	 * \brief 构造函数
	 * \param mon 风险监控器指针
	 * \param fact 风险监控器工厂指针
	 */
	WtRiskMonWrapper(WtRiskMonitor* mon, IRiskMonitorFact* fact) :_mon(mon), _fact(fact){}
	
	/*!
	 * \brief 析构函数
	 * \details 自动释放风险监控器资源
	 */
	~WtRiskMonWrapper()
	{
		if (_mon)
		{
			_fact->deleteRiskMonotor(_mon);
		}
	}

	/*!
	 * \brief 获取风险监控器指针
	 * \return 风险监控器指针
	 */
	WtRiskMonitor* self(){ return _mon; }


private:
	WtRiskMonitor*		_mon;		/*!< 风险监控器指针 */
	IRiskMonitorFact*	_fact;		/*!< 风险监控器工厂指针 */
};

/*!
 * \brief 风险监控器智能指针类型定义
 */
typedef std::shared_ptr<WtRiskMonWrapper>	WtRiskMonPtr;

/*!
 * \class IEngineEvtListener
 * \brief 引擎事件监听器接口
 * 
 * \details 定义引擎事件回调接口，用于处理引擎的各种事件通知
 */
class IEngineEvtListener
{
public:
	/*!
	 * \brief 初始化事件回调
	 * \details 引擎初始化完成时触发
	 */
	virtual void on_initialize_event() {}
	
	/*!
	 * \brief 调度事件回调
	 * \param uDate 日期，格式YYYYMMDD
	 * \param uTime 时间，格式HHMM
	 * \details 定时调度事件触发时调用
	 */
	virtual void on_schedule_event(uint32_t uDate, uint32_t uTime) {}
	
	/*!
	 * \brief 交易时段事件回调
	 * \param uDate 日期，格式YYYYMMDD
	 * \param isBegin 是否为时段开始，true-开始，false-结束
	 * \details 交易时段开始或结束时触发
	 */
	virtual void on_session_event(uint32_t uDate, bool isBegin = true) {}
};

/*!
 * \class WtEngine
 * \brief WonderTrader交易引擎基类
 * 
 * \details 交易引擎基类，提供以下核心功能：
 *          
 *          **数据管理**：
 *          - 行情数据订阅和处理
 *          - 基础数据管理（品种、合约、交易时段）
 *          - 历史数据查询和缓存
 *          
 *          **交易管理**：
 *          - 信号生成和过滤
 *          - 持仓管理和盈亏计算
 *          - 手续费计算和资金管理
 *          
 *          **风险控制**：
 *          - 风险监控器集成
 *          - 交易风险检查
 *          - 资金风险管理
 *          
 *          **事件处理**：
 *          - 行情事件处理
 *          - 交易时段事件处理
 *          - 异步任务调度
 *          
 * \note 这是一个抽象基类，具体的引擎实现需要继承此类
 * \see WtCtaEngine, WtHftEngine, WtSelEngine
 */
class WtEngine : public WtPortContext, public IParserStub
{
public:
	/*!
	 * \brief 构造函数
	 */
	WtEngine();

	/*!
	 * \brief 设置交易适配器管理器
	 * \param mgr 交易适配器管理器指针
	 */
	inline void set_adapter_mgr(TraderAdapterMgr* mgr) { _adapter_mgr = mgr; }

	/*!
	 * \brief 设置当前日期时间
	 * \param curDate 当前日期，格式YYYYMMDD
	 * \param curTime 当前时间，格式HHMM
	 * \param curSecs 当前秒数，默认为0
	 * \param rawTime 原始时间，默认为0
	 */
	void set_date_time(uint32_t curDate, uint32_t curTime, uint32_t curSecs = 0, uint32_t rawTime = 0);

	/*!
	 * \brief 设置交易日期
	 * \param curTDate 当前交易日期，格式YYYYMMDD
	 */
	void set_trading_date(uint32_t curTDate);

	/*!
	 * \brief 获取当前日期
	 * \return 当前日期，格式YYYYMMDD
	 */
	inline uint32_t get_date() { return _cur_date; }
	
	/*!
	 * \brief 获取当前分钟时间
	 * \return 当前时间，格式HHMM
	 */
	inline uint32_t get_min_time() { return _cur_time; }
	
	/*!
	 * \brief 获取原始时间
	 * \return 原始时间
	 */
	inline uint32_t get_raw_time() { return _cur_raw_time; }
	
	/*!
	 * \brief 获取当前秒数
	 * \return 当前秒数
	 */
	inline uint32_t get_secs() { return _cur_secs; }
	
	/*!
	 * \brief 获取交易日期
	 * \return 交易日期，格式YYYYMMDD
	 */
	inline uint32_t get_trading_date() { return _cur_tdate; }

	/*!
	 * \brief 获取基础数据管理器
	 * \return 基础数据管理器指针
	 */
	inline IBaseDataMgr*		get_basedata_mgr(){ return _base_data_mgr; }
	
	/*!
	 * \brief 获取热点管理器
	 * \return 热点管理器指针
	 */
	inline IHotMgr*				get_hot_mgr() { return _hot_mgr; }
	
	/*!
	 * \brief 获取交易时段信息
	 * \param sid 时段ID或合约代码
	 * \param isCode 是否为合约代码，默认false
	 * \return 交易时段信息指针
	 */
	WTSSessionInfo*		get_session_info(const char* sid, bool isCode = false);
	
	/*!
	 * \brief 获取品种信息
	 * \param stdCode 标准合约代码
	 * \return 品种信息指针
	 */
	WTSCommodityInfo*	get_commodity_info(const char* stdCode);
	
	/*!
	 * \brief 获取合约信息
	 * \param stdCode 标准合约代码
	 * \return 合约信息指针
	 */
	WTSContractInfo*	get_contract_info(const char* stdCode);

	/*!
	 * \brief 获取最新tick数据
	 * \param sid 策略ID
	 * \param stdCode 标准合约代码
	 * \return 最新tick数据指针
	 */
	WTSTickData*	get_last_tick(uint32_t sid, const char* stdCode);
	
	/*!
	 * \brief 获取tick数据切片
	 * \param sid 策略ID
	 * \param stdCode 标准合约代码
	 * \param count 数据条数
	 * \return tick数据切片指针
	 */
	WTSTickSlice*	get_tick_slice(uint32_t sid, const char* stdCode, uint32_t count);
	
	/*!
	 * \brief 获取K线数据切片
	 * \param sid 策略ID
	 * \param stdCode 标准合约代码
	 * \param period K线周期
	 * \param count 数据条数
	 * \param times 周期倍数，默认1
	 * \param etime 结束时间，默认0表示最新
	 * \return K线数据切片指针
	 */
	WTSKlineSlice*	get_kline_slice(uint32_t sid, const char* stdCode, const char* period, uint32_t count, uint32_t times = 1, uint64_t etime = 0);

	/*!
	 * \brief 订阅tick数据
	 * \param sid 策略ID
	 * \param code 合约代码
	 */
	void sub_tick(uint32_t sid, const char* code);

	/*!
	 * \brief 获取当前价格
	 * \param stdCode 标准合约代码
	 * \return 当前价格
	 */
	double get_cur_price(const char* stdCode);

	/*!
	 * \brief 计算手续费
	 * \param stdCode 标准合约代码
	 * \param price 价格
	 * \param qty 数量
	 * \param offset 开平标志
	 * \return 手续费金额
	 */
	double calc_fee(const char* stdCode, double price, double qty, uint32_t offset);

	/*!
	 * \brief 设置风险监控器
	 * \param monitor 风险监控器智能指针
	 */
	inline void setRiskMonitor(WtRiskMonPtr& monitor)
	{
		_risk_mon = monitor;
	}

	/*!
	 * \brief 注册事件监听器
	 * \param listener 事件监听器指针
	 */
	inline void regEventListener(IEngineEvtListener* listener)
	{
		_evt_listener = listener;
	}

	//////////////////////////////////////////////////////////////////////////
	//WtPortContext接口实现
	/*!
	 * \brief 获取资金信息
	 * \return 组合资金信息指针
	 */
	virtual WTSPortFundInfo* getFundInfo() override;

	/*!
	 * \brief 设置成交量放大倍数
	 * \param scale 放大倍数
	 */
	virtual void setVolScale(double scale) override;

	/*!
	 * \brief 判断是否在交易时段
	 * \return true-在交易时段，false-不在交易时段
	 */
	virtual bool isInTrading() override;

	/*!
	 * \brief 写入风险日志
	 * \param message 日志消息
	 */
	virtual void writeRiskLog(const char* message) override;

	/*!
	 * \brief 获取当前日期
	 * \return 当前日期，格式YYYYMMDD
	 */
	virtual uint32_t	getCurDate() override;
	
	/*!
	 * \brief 获取当前时间
	 * \return 当前时间，格式HHMM
	 */
	virtual uint32_t	getCurTime() override;
	
	/*!
	 * \brief 获取交易日期
	 * \return 交易日期，格式YYYYMMDD
	 */
	virtual uint32_t	getTradingDate() override;
	
	/*!
	 * \brief 时间转换为分钟
	 * \param uTime 时间
	 * \return 分钟数
	 */
	virtual uint32_t	transTimeToMin(uint32_t uTime) override{ return 0; }

	//////////////////////////////////////////////////////////////////////////
	/// IParserStub接口实现
	/*!
	 * \brief 处理推送的行情数据
	 * \param newTick 新的tick数据
	 * \param hotFlag 热点标志
	 */
	virtual void handle_push_quote(WTSTickData* newTick, uint32_t hotFlag) override;

public:
	/*!
	 * \brief 初始化引擎
	 * \param cfg 配置信息
	 * \param bdMgr 基础数据管理器
	 * \param dataMgr 数据管理器
	 * \param hotMgr 热点管理器
	 * \param notifier 事件通知器
	 */
	virtual void init(WTSVariant* cfg, IBaseDataMgr* bdMgr, WtDtMgr* dataMgr, IHotMgr* hotMgr, EventNotifier* notifier);

	/*!
	 * \brief 运行引擎
	 * \param bAsync 是否异步运行，默认false
	 */
	virtual void run(bool bAsync = false) = 0;

	/*!
	 * \brief tick数据回调
	 * \param stdCode 标准合约代码
	 * \param curTick 当前tick数据
	 */
	virtual void on_tick(const char* stdCode, WTSTickData* curTick);

	/*!
	 * \brief K线数据回调
	 * \param stdCode 标准合约代码
	 * \param period K线周期
	 * \param times 周期倍数
	 * \param newBar 新的K线数据
	 */
	virtual void on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) = 0;

	/*!
	 * \brief 初始化回调
	 */
	virtual void on_init(){}
	
	/*!
	 * \brief 交易时段开始回调
	 */
	virtual void on_session_begin();
	
	/*!
	 * \brief 交易时段结束回调
	 */
	virtual void on_session_end();


protected:
	/*!
	 * \brief 加载手续费配置
	 * \param filename 配置文件路径
	 */
	void		load_fees(const char* filename);

	/*!
	 * \brief 加载数据
	 */
	void		load_datas();

	/*!
	 * \brief 保存数据
	 */
	void		save_datas();

	/*!
	 * \brief 追加信号
	 * \param stdCode 标准合约代码
	 * \param qty 数量
	 * \param bStandBy 是否待机
	 */
	void		append_signal(const char* stdCode, double qty, bool bStandBy);

	/*!
	 * \brief 设置持仓
	 * \param stdCode 标准合约代码
	 * \param qty 数量
	 * \param curPx 当前价格，默认-1
	 */
	void		do_set_position(const char* stdCode, double qty, double curPx = -1);

	/*!
	 * \brief 任务循环
	 */
	void		task_loop();

	/*!
	 * \brief 推送任务
	 * \param task 任务项
	 */
	void		push_task(TaskItem task);

	/*!
	 * \brief 更新资金动态盈亏
	 */
	void		update_fund_dynprofit();

	/*!
	 * \brief 初始化风险监控
	 * \param cfg 配置信息
	 * \return 初始化是否成功
	 */
	bool		init_riskmon(WTSVariant* cfg);

private:
	/*!
	 * \brief 初始化输出
	 */
	void		init_outputs();
	
	/*!
	 * \brief 记录交易日志
	 * \param stdCode 标准合约代码
	 * \param isLong 是否多头
	 * \param isOpen 是否开仓
	 * \param curTime 当前时间
	 * \param price 价格
	 * \param qty 数量
	 * \param fee 手续费，默认0.0
	 */
	inline void	log_trade(const char* stdCode, bool isLong, bool isOpen, uint64_t curTime, double price, double qty, double fee = 0.0);
	
	/*!
	 * \brief 记录平仓日志
	 * \param stdCode 标准合约代码
	 * \param isLong 是否多头
	 * \param openTime 开仓时间
	 * \param openpx 开仓价格
	 * \param closeTime 平仓时间
	 * \param closepx 平仓价格
	 * \param qty 数量
	 * \param profit 盈亏
	 * \param totalprofit 总盈亏，默认0
	 */
	inline void	log_close(const char* stdCode, bool isLong, uint64_t openTime, double openpx, uint64_t closeTime, double closepx, double qty,
		double profit, double totalprofit = 0);

protected:
	uint32_t		_cur_date;		/*!< 当前日期 */
	uint32_t		_cur_time;		/*!< 当前时间，以1分钟为单位，如0900，如果时间是1分钟以内如0901，_cur_time也是0901，主要是为了CTA策略方便 */
	uint32_t		_cur_raw_time;	/*!< 当前真实时间 */
	uint32_t		_cur_secs;		/*!< 当前秒数，绝对秒数 */
	uint32_t		_cur_tdate;		/*!< 当前交易日 */

	uint32_t		_fund_udt_span;	/*!< 资金更新时间间隔 */

	IBaseDataMgr*	_base_data_mgr;	/*!< 基础数据管理器 */
	IHotMgr*		_hot_mgr;		/*!< 热点管理器 */
	WtDtMgr*		_data_mgr;		/*!< 数据管理器 */
	IEngineEvtListener*	_evt_listener;	/*!< 事件监听器 */

	//By Wesley @ 2022.02.07
	//tick数据订阅，first是contextid，second是订阅选项：0-原始数据模式，1-前复权，2-后复权
	/*!
	 * \brief 订阅选项类型定义
	 * \details first是contextid，second是订阅选项：0-原始数据模式，1-前复权，2-后复权
	 */
	typedef std::pair<uint32_t, uint32_t> SubOpt;
	typedef faster_hashmap<uint32_t, SubOpt> SubList;
	typedef faster_hashmap<LongKey, SubList>	StraSubMap;
	StraSubMap		_tick_sub_map;	/*!< tick数据订阅表 */
	StraSubMap		_bar_sub_map;	/*!< K线数据订阅表 */

	//By Wesley @ 2022.02.07 
	//这个容器没有用到，先注释掉
	//faster_hashset<std::string>		_ticksubed_raw_codes;	//tick订阅表，真实代码模式
	

	//////////////////////////////////////////////////////////////////////////
	//信号信息结构
	/*!
	 * \struct _SigInfo
	 * \brief 信号信息结构
	 */
	typedef struct _SigInfo
	{
		double		_volume;	/*!< 信号数量 */
		uint64_t	_gentime;	/*!< 生成时间 */

		_SigInfo()
		{
			_volume = 0;
			_gentime = 0;
		}
	}SigInfo;
	typedef faster_hashmap<LongKey, SigInfo>	SignalMap;
	SignalMap		_sig_map;	/*!< 信号映射表 */

	//////////////////////////////////////////////////////////////////////////
	//信号过滤器
	WtFilterMgr		_filter_mgr;	/*!< 信号过滤管理器 */
	EventNotifier*	_notifier;		/*!< 事件通知器 */

	//////////////////////////////////////////////////////////////////////////
	//手续费模块
	/*!
	 * \struct _FeeItem
	 * \brief 手续费项结构
	 */
	typedef struct _FeeItem
	{
		double	_open;			/*!< 开仓手续费 */
		double	_close;			/*!< 平仓手续费 */
		double	_close_today;	/*!< 平今手续费 */
		bool	_by_volume;		/*!< 是否按手数计算 */

		_FeeItem()
		{
			memset(this, 0, sizeof(_FeeItem));
		}
	} FeeItem;
	typedef faster_hashmap<LongKey, FeeItem>	FeeMap;
	FeeMap		_fee_map;	/*!< 手续费映射表 */
	

	WTSPortFundInfo*	_port_fund;	/*!< 组合资金信息 */

	//////////////////////////////////////////////////////////////////////////
	//持仓管理
	/*!
	 * \struct _DetailInfo
	 * \brief 持仓明细信息结构
	 */
	typedef struct _DetailInfo
	{
		bool		_long;		/*!< 是否多头 */
		double		_price;		/*!< 开仓价格 */
		double		_volume;	/*!< 持仓数量 */
		uint64_t	_opentime;	/*!< 开仓时间 */
		uint32_t	_opentdate;	/*!< 开仓交易日 */
		double		_profit;	/*!< 浮动盈亏 */

		_DetailInfo()
		{
			memset(this, 0, sizeof(_DetailInfo));
		}
	} DetailInfo;

	/*!
	 * \struct _PosInfo
	 * \brief 持仓信息结构
	 */
	typedef struct _PosInfo
	{
		double		_volume;		/*!< 总持仓数量 */
		double		_closeprofit;	/*!< 平仓盈亏 */
		double		_dynprofit;		/*!< 动态盈亏 */

		std::vector<DetailInfo> _details;	/*!< 持仓明细列表 */

		_PosInfo()
		{
			_volume = 0;
			_closeprofit = 0;
			_dynprofit = 0;
		}
	} PosInfo;
	typedef faster_hashmap<LongKey, PosInfo> PositionMap;
	PositionMap		_pos_map;	/*!< 持仓映射表 */

	//////////////////////////////////////////////////////////////////////////
	//价格缓存
	typedef faster_hashmap<LongKey, double> PriceMap;
	PriceMap		_price_map;	/*!< 价格映射表 */

	//后台任务线程，已分离和异步，持仓更新都丢到后台线程里去
	/*!
	 * \brief 任务队列类型定义
	 */
	typedef std::queue<TaskItem>	TaskQueue;
	StdThreadPtr	_thrd_task;		/*!< 后台任务线程 */
	TaskQueue		_task_queue;	/*!< 任务队列 */
	StdUniqueMutex	_mtx_task;		/*!< 任务队列互斥锁 */
	StdCondVariable	_cond_task;		/*!< 任务队列条件变量 */
	bool			_terminated;	/*!< 是否已终止 */

	/*!
	 * \struct _RiskMonFactInfo
	 * \brief 风险监控工厂信息结构
	 */
	typedef struct _RiskMonFactInfo
	{
		std::string		_module_path;	/*!< 模块路径 */
		DllHandle		_module_inst;	/*!< 模块实例 */
		IRiskMonitorFact*	_fact;		/*!< 工厂指针 */
		FuncCreateRiskMonFact	_creator;	/*!< 创建函数 */
		FuncDeleteRiskMonFact	_remover;	/*!< 删除函数 */
	} RiskMonFactInfo;
	RiskMonFactInfo	_risk_fact;		/*!< 风险监控工厂信息 */
	WtRiskMonPtr	_risk_mon;		/*!< 风险监控器 */
	double			_risk_volscale;	/*!< 风险成交量放大倍数 */
	uint32_t		_risk_date;		/*!< 风险日期 */

	TraderAdapterMgr*	_adapter_mgr;	/*!< 交易适配器管理器 */

	BoostFilePtr	_trade_logs;	/*!< 交易日志文件 */
	BoostFilePtr	_close_logs;	/*!< 平仓日志文件 */

	faster_hashmap<LongKey, double>	_factors_cache;	/*!< 复权因子缓存 */

	//用于标记是否已经初始化tickle
	bool			_ready;		/*!< 是否已就绪 */
};
NS_WTP_END